/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.imagepipeline.bitmaps;

import com.facebook.common.logging.FLog;
import com.facebook.common.memory.PooledByteBuffer;
import com.facebook.common.references.CloseableReference;
import com.facebook.imageformat.DefaultImageFormats;
import com.facebook.imagepipeline.core.CloseableReferenceFactory;
import com.facebook.imagepipeline.image.EncodedImage;
import com.facebook.imagepipeline.platform.PlatformDecoder;
import ohos.agp.utils.Color;
import ohos.media.image.PixelMap;
import ohos.media.image.common.AlphaType;
import ohos.media.image.common.PixelFormat;

import javax.annotation.concurrent.ThreadSafe;

/**
 * Factory implementation for Honeycomb through Kitkat
 */
@ThreadSafe
public class HoneycombBitmapFactory extends PlatformBitmapFactory {

    private static final String TAG = HoneycombBitmapFactory.class.getSimpleName();
    private final EmptyJpegGenerator mJpegGenerator;
    private final PlatformDecoder mPurgeableDecoder;
    private final CloseableReferenceFactory mCloseableReferenceFactory;
    private boolean mImmutableBitmapFallback;

    public HoneycombBitmapFactory(
            EmptyJpegGenerator jpegGenerator,
            PlatformDecoder purgeableDecoder,
            CloseableReferenceFactory closeableReferenceFactory) {
        mJpegGenerator = jpegGenerator;
        mPurgeableDecoder = purgeableDecoder;
        mCloseableReferenceFactory = closeableReferenceFactory;
    }

    /**
     * Creates a bitmap of the specified width and height.
     *
     * @param width        the width of the bitmap
     * @param height       the height of the bitmap
     * @param bitmapConfig the {@link android.graphics.Bitmap.Config} used to create the decoded
     *                     Bitmap
     * @return a reference to the bitmap
     * @throws TooManyBitmapsException if the pool is full
     * @throws OutOfMemoryError        if the Bitmap cannot be allocated
     */
    @Override
    public CloseableReference<PixelMap> createBitmapInternal(
            int width, int height, PixelFormat bitmapConfig) {
        if (mImmutableBitmapFallback) {
            return createFallbackBitmap(width, height, bitmapConfig);
        }
        CloseableReference<PooledByteBuffer> jpgRef =
                mJpegGenerator.generate((short) width, (short) height);
        try {
            EncodedImage encodedImage = new EncodedImage(jpgRef);
            encodedImage.setImageFormat(DefaultImageFormats.JPEG);
            try {
                CloseableReference<PixelMap> bitmapRef =
                        mPurgeableDecoder.decodeJPEGFromEncodedImage(
                                encodedImage, bitmapConfig, null, jpgRef.get().size());
                if (!bitmapRef.get().isEditable()) {
                    CloseableReference.closeSafely(bitmapRef);
                    mImmutableBitmapFallback = true;
                    FLog.wtf(TAG, "Immutable bitmap returned by decoder");
                    // On some devices (Samsung GT-S7580) the returned bitmap can be immutable, in that case
                    // let's jut use Bitmap.createBitmap() to hopefully create a mutable one.
                    return createFallbackBitmap(width, height, bitmapConfig);
                }
                //bitmapRef.get().setHasAlpha(true);
                bitmapRef.get().setAlphaType(AlphaType.UNKNOWN);
                //bitmapRef.get().eraseColor(Color.TRANSPARENT);
                bitmapRef.get().writePixels(0x00000000);
                return bitmapRef;
            } finally {
                EncodedImage.closeSafely(encodedImage);
            }
        } finally {
            jpgRef.close();
        }
    }

    private CloseableReference<PixelMap> createFallbackBitmap(
            int width, int height, PixelFormat bitmapConfig) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = bitmapConfig;
        initializationOptions.size.width = width;
        initializationOptions.size.height = height;
        return mCloseableReferenceFactory.create(PixelMap.create(initializationOptions), SimpleBitmapReleaser.getInstance());
    }
}
